<?php
/**
 * Data models needed by the kasahorow content creation modules.
 */
define('TEMPLATE_DISABLED', 0);
define('TEMPLATE_ENABLED', 1);
define('TEMPLATE_FEATURED', 2);

class EntryTemplate extends KDatabase{
  public $created;
  public $description;
  public $editors; # List of User IDs of editors
  public $fields; # Hash map of fields accepted by this template
  public $id;
  public $links; # List of other templates entries of this type can be linked to
  public $name;
  public $saved; # True if model has been saved. False otherwise
  public $status;
  public $vocabulary; # Drupal vocabulary ID

  public function __construct($id) {
    $this->id = $id;
    $this->saved = False;
    $this->status = TEMPLATE_ENABLED;
    $this->fields = $this->getFields();
  }

  public function save() {
    if($this->id) {
      $this->created = time();
      $this->saved = db_query("INSERT INTO {kdictionary}(name, `index`, editor,
                       status, iso, vid, instruction, 
                       created) VALUES('%s', '%s', '%s', '%s', '%s',
                       '%d', '%s', %d)",
                       $this->name, serialize($this->links), 
                       serialize($this->editors), $this->status, $this->id,
                       $this->vocabulary, $this->description, $this->created);
    }
  }

  public function get() {
    $this->Table = 'kdictionary';
    $row = $this->RetrieveRow(array('wheres' => array("iso='$this->id'"),
                                    'debug' => 0));
    $this->created = $row->created;
    $this->id = $row->iso;
    $this->description = $row->instruction;
    $this->editors = unserialize($row->editor);
    $this->links = unserialize($row->index);
    $this->name = $row->name;
    return $this;
  }

  public function getFields() {
    $fields = array('title' => 'Title', 'body' => 'Body', 'group' => 'Group',
                    'sample' => 'Sample'); # Default fields
    $this->Table = 'kentry_fields';
    $rows = $this->RetrieveRows(array('wheres' => array("iso='$this->id'"),
                                      'debug' => 0));
    foreach($rows as $row) {
      $fields[$row->kfid] = sprintf('%s: %s', strtoupper($row->ftype), $row->label);
    }
    return $fields;
  }
}

class EntryField extends KDatabase {
  public $field_id;
  public $label;
  public $name;
  public $description;
  public $template_id; # Maps to iso field in kdictionary table
  public $field_type;
  public $required;
  public $options; # List of options
  public $saved; # True if field is saved. False otherwise

  public function __construct($template_id) {
    $this->template_id = $template_id;
  }

  public function save() {
    $this->saved = db_query('INSERT INTO {kentry_fields}(iso, label, ftype)
                     VALUES("%s", "%s", "%s")',
                     $this->template_id, $this->label, $this->field_type
                    );
    $this->field_id = db_last_insert_id('kentry_fields');
  }
  
  public function get() {
    $this->Table = 'kentry_fields';
    $row = $this->RetrieveRow(array('wheres' => array("kfid=$this->field_id"),
                                    'debug' => 0));
    $this->field_id = $row->kfid;
    $this->field_type = $row->ftype;
    $this->description = $row->explanation;
    $this->label = $row->label;
    $this->options = unserialize($row->options);
    return $this;

  }
}

/**
 * Field data values
 */
class EntryFieldData extends KDatabase {
  public $field_id;
  public $entry_id;
  public $data;
}

class EntryRelation extends KDatabase {
  public $uid;
  public $from_nid;
  public $to_nid;
  public $rel_id;
  public $saved;
  public $updated;

  private $vid; # Node vid of $from_nid
  private $svid; # Node vid of $to_nid
  function __construct($from_nid, $to_nid, $rel_id) {
    $this->from_nid = $from_nid;
    $this->vid = _kentry_vid_from_nid($from_nid);
    $this->svid = _kentry_vid_from_nid($to_nid);
    $this->to_nid = $to_nid;
    $this->rel_id = $rel_id;

    $this->Table = 'kentry_synonyms';
  }

  function save() {
     $this->updated = time();
     $this->saved = db_query("INSERT IGNORE {kentry_synonyms}
                                       (vid, svid, iso, relid, uid, updated)
                                       VALUES (%d, %d, '%s', '%s', %d, %d);\n",
                                       $this->vid, $this->svid, $iso,
                                       $this->rel_id, $this->uid,
                                       $this->updated);

  }

  function get() {
    $row = $this->RetrieveRow(array('wheres' => array("vid=$this->vid",
                                                      "svid=$this->svid",
                                                      "relid='$this->rel_id'"),
                                    'debug' => 0));
    $this->relation_id = $row->relid;
    $this->uid = $row->uid;
    return $this;
  }
}

class Entry extends KDatabase {
  public $entry_id;
  public $fields; # An associative array of field_ids and values
  public $type;
  public $author_id; # Drupal UID of creator of entry
  public $saved;
  public $status;

  private $vid;

  function __construct($nid=null) {
    $this->entry_id = $nid;
    if($nid) {
      $this->vid = _kentry_vid_from_nid($nid);
      $this->fields = $this->getFieldValues();
    }
    $this->Table = 'kentry';
  }

  function save() {
    $node = new stdClass();
    $node->type = $this->getType(); 

    # If entry_id is not set, it's a new entry
    if(!$this->entry_id) {
      if(trim($node->type)) {
        $node->uid = ($this->author_id>0)?$this->author_id:0; # Default to anonymous user
        $node->status = 1; #is_int($this->status)?$this->status:1;
        $node->language = $this->fields['language'];
        node_save($node);
        $this->entry_id = $node->nid;
        $this->vid = _kentry_vid_from_nid($this->entry_id);

        $this->saveFields($node);
        $this->saved = isset($node->nid);
      }else {
        $this->saved = false; # Cannot save entries without a type
      }
    }else {
      # Else, it's an update of an existing entry
      $node->nid = $this->entry_id;
      $node->vid = _kentry_vid_from_nid($this->entry_id);
      $this->saveFields($node);
      $this->saved = isset($node->nid);
    }
  }

  private function getType() {
    if($this->type) {
      $type = str_replace('kentry_', '', $this->type); # Strip out old-style prefixes
    }else if(!empty($this->fields)) {
      $kfids = array_keys($this->fields);
      $type = db_result(db_query("SELECT iso FROM {kentry_fields} WHERE kfid=%d", $kfids[0]));
    }else {
      $type = false; # Could not detect a type
    }
    return $type;
  }

  private function saveFields($node) {
    # Save into Drupal node tables
    db_query("UPDATE {node} SET title='%s' WHERE vid=%d", 
              $this->fields['title'], $node->vid);
    db_query("UPDATE {node_revisions} SET title='%s', body='%s' WHERE vid=%d", 
              $this->fields['title'], $this->fields['body'], $node->vid);

    # Save into kentry table
    $tpl = new EntryTemplate($this->type);
    $default_fields = array_keys($tpl->fields); 
    db_query("UPDATE {kentry} SET word='%s', defn='%s', example='%s', iso='%s' 
              WHERE vid=%d", 
             $this->fields['group'], $this->fields['body'], 
             $this->fields['sample'], $this->type, $node->vid);

    if($this->fields['pcat']) {
      db_query("UPDATE {kentry} SET partofspeech=%d WHERE vid=%d",
               $this->fields['pcat'], $node->vid);
      db_query("REPLACE INTO {term_node}(nid, vid, tid) VALUES(%d, %d, %d)",
               $node->nid, $node->vid, $this->fields['pcat']);
    }

    if($this->fields['promote']) {
      db_query("UPDATE {node} SET promote=%d WHERE vid=%d",
               $this->fields['promote'], $node->vid);
    }

    if(trim($this->fields['media'])) {
      include_once(drupal_get_path('module', 'kentry').'/kentry.admin.inc');
      $field = _kentry_upload_field($node);
      if($field->kfid) {
        _kentry_field_save($field->kfid, $node->vid, $this->fields['media']);
      }
    }
    # Save into kentry_values table
    foreach($this->fields as $kfid => $value) {
      if((int)$kfid == 0) { continue; }
      if(!db_result(db_query("SELECT vid FROM {kentry_values} WHERE vid=%d AND kfid='%s'", $node->vid, $kfid))) {
        db_query("INSERT INTO {kentry_values}(vid, kfid, value) 
                  VALUES(%d, '%s', '%s')", $node->vid, $kfid, $value);
      }else {
        db_query("UPDATE {kentry_values} SET value='%s' WHERE 
                  kfid='%s' AND vid=%d", $value, $kfid, $node->vid);

      }
    }
  }

  private function getFieldValues() {
    $this->Table = 'node_revisions';
    $main = $this->RetrieveRow(array('cols' => array('title', 'body'),
                                     'wheres' => array("vid=$this->vid"),
                                     'debug' => 0));
    $this->Table = 'kentry';
    $aux = $this->RetrieveRow(array('cols' => array('word', 'example'),
                                     'wheres' => array("vid=$this->vid"),
                                     'debug' => 0));
    
    $this->fields = array('title' => $main->title, 'body' => $main->body,
                          'group' => $aux->word, 'sample' => $aux->example);
    $this->fields['pcat'] = db_result(db_query("SELECT tid FROM {term_node}
                                                WHERE vid=%d", $this->vid));
    $media = db_fetch_object(db_query("SELECT v.kfid, v.value FROM {kentry_fields} f
                                                 INNER JOIN {kentry_values} v ON
                                                 f.kfid=v.kfid WHERE f.iso='_auto' AND
                                                 v.vid=%d", $this->vid));
    if(trim($media->value)) {
      $this->fields['media'] = $media->value;
    }
    
    $this->Table = 'kentry_values';
    $others = $this->RetrieveRows(array('cols' => array('kfid', 'value'),
                                        'wheres' => array("vid=$this->vid", 
                                                          "kfid!=$media->kfid",),
                                        'debug' => 0));
    foreach($others as $row) {
      $this->fields[$row->kfid] = $row->value;
    }
    return $this->fields;
  }
 
  function get() {
    #$row = node_load(array('nid' => $this->entry_id)); # Not working
    $this->Table = 'node';
    $row = $this->RetrieveRow(array('wheres' => array("vid=$this->vid"), 
                                    'debug' => 0));
    $this->status = $row->status;
    $this->author_id = $row->uid;
    $this->type = $row->type;
    $this->saved = True;
    $this->getFieldValues();
    return $this;
  }
}


## Utility functions ##
function _kentry_vid_from_nid($nid) {
  return (int)db_result(db_query('SELECT vid FROM {node} WHERE nid=%d', $nid));
}

function _kentry_nid_from_vid($vid) {
  return (int)db_result(db_query('SELECT nid FROM {node} WHERE vid=%d', $vid));
}
